home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / map / gc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-11-12  |  4.9 KB  |  195 lines

  1. /*
  2.  *      gc.c
  3.  *
  4.  *      Great Circle.  This program is used to determine bearing
  5.  *      and range to two stations given latitude and longitude.
  6.  *
  7.  *      Ver 1.04 By S. R. Sampson, N5OWK
  8.  *      Public Domain (p) April 1991
  9.  *
  10.  *      Ref: Air Force Manual 51-40, "Air Navigation", 1 February 1987
  11.  *
  12.  *      Usage examples:
  13.  *
  14.  *      gc 35.19n97.27w 0s0e            (Moore to Prime/Equator)
  15.  *      gc 35.19N97.27W 38.51n77.02W    (Moore to Washington D.C.)
  16.  *      gc 33.56n118.24w 55.45n37.35e   (L.A. to Moscow U.S.S.R.)
  17.  *    gc 35N70W 35N71W        (No decimal points used)
  18.  */
  19.  
  20. /* Includes */
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <ctype.h>
  25. #include <math.h>
  26.  
  27. /* Defines */
  28.  
  29. #define RADIAN  (180.0 / M_PI)
  30.  
  31. /* Simple Declare, No Prototypes */
  32.  
  33. /*
  34.  *      Error routine
  35.  */
  36.  
  37. void err(type)
  38. int     type;
  39. {
  40.         switch(type)  {
  41.         case 1:
  42.                 printf("\007Latitude Out of Range (90N to 90S)\n");
  43.                 break;
  44.         case 2:
  45.                 printf("\007Longitude Out of Range (180W to 180E)\n");
  46.                 break;
  47.         case 3:
  48.                 printf("\007Minutes Out of Range (0 to 59)\n");
  49.         }
  50.  
  51.         exit(1);
  52. }
  53.  
  54. /*
  55.  *      Convert Degrees and Minutes to Decimal
  56.  */
  57.  
  58. double dm2dec(n)
  59. double  n;
  60. {
  61.         double  t;
  62.  
  63.         t = (int)n;
  64.         n -= t;
  65.         n /= .60;
  66.  
  67.         if (n >= 1.0)
  68.                 err(3);
  69.  
  70.         return (n + t);
  71. }
  72.  
  73. /*
  74.  *      Parse the input line
  75.  *
  76.  *      dd(.mm)[NnSs]ddd(.mm)[EeWw]
  77.  */
  78.  
  79. void parse(s, lat, lon)
  80. char    *s;
  81. double  *lat, *lon;
  82. {
  83.         register char   *i, *t;
  84.         int             l;
  85.  
  86.         l = strlen(s);
  87.         for (i = s; i < (s + l); ++i)  {
  88.                 switch(toupper(*i))  {
  89.                 case 'N':
  90.                         *i = '\0';
  91.                         t = i + 1;
  92.                         *lat = atof(s);
  93.                         break;
  94.                 case 'S':
  95.                         *i = '\0';
  96.                         t = i + 1;
  97.                         *lat = -atof(s);
  98.                         break;
  99.                 case 'E':
  100.                         *i = '\0';
  101.                         *lon = -atof(t);
  102.                         break;
  103.                 case 'W':
  104.                         *i = '\0';
  105.                         *lon = atof(t);
  106.                 }
  107.         }
  108.  
  109.         *lat = dm2dec(*lat);
  110.         *lon = dm2dec(*lon);
  111.  
  112.         if (*lat > 90.0 || *lat < -90.0)
  113.                 err(1);
  114.  
  115.         if (*lon > 180.0 || *lon < -180.0)
  116.                 err(2);
  117.  
  118.         /* Prevent ACOS() Domain Error */
  119.  
  120.         if (*lat == 90.0)
  121.                 *lat = 89.9;
  122.  
  123.         if (*lat == -90.0)
  124.                 *lat = -89.9;
  125. }
  126.  
  127. void main(argc, argv)
  128. int  argc;
  129. char **argv;
  130. {
  131.     double    x, y, tmp, dist, range, TO_Bearing, FROM_Bearing;
  132.     double  QTH_Lat, QTH_Long, DEST_Lat, DEST_Long, Delta_Long;
  133.  
  134.         if (argc != 3)  {
  135.             printf("Usage: gc station1 station2\n\n" \
  136.             "This program computes Great Circle Bearing and Range\n" \
  137.             "given the latitude and longitude (degrees and minutes).\n\n" \
  138.             "You must input the lat/long of the two stations.\n" \
  139.             "The output will then be relative from station1 to station2.\n\n" \
  140.             "Input the two station lat/longs using the following format:\n\n" \
  141.             "\tdd.mmHddd.mmG  lead/lagging zeros can be left out.\n\n" \
  142.             "d = Degrees, m = Minutes, H = Hemisphere (N or S), " \
  143.         "G = Greenwich (W or E)\n");
  144.  
  145.                 exit(1);
  146.         }
  147.  
  148.         /* Process the command line data */
  149.  
  150.         parse(argv[1], &QTH_Lat, &QTH_Long);
  151.         parse(argv[2], &DEST_Lat, &DEST_Long);
  152.  
  153.         /* Compute the Bearing and Range, From the Formula in Chapter 23 */
  154.  
  155.         Delta_Long = DEST_Long - QTH_Long;
  156.  
  157.         QTH_Lat    /= RADIAN;   /* Convert variables to Radians */
  158.         QTH_Long   /= RADIAN;
  159.         DEST_Lat   /= RADIAN;
  160.         Delta_Long /= RADIAN;
  161.  
  162.         tmp = (sin(QTH_Lat) * sin(DEST_Lat)) +
  163.                 (cos(QTH_Lat) * cos(DEST_Lat) * cos(Delta_Long));
  164.  
  165.         dist = acos(tmp);
  166.         range = 60.0 * (dist * RADIAN);    /* change to nautical miles */
  167.  
  168.         x = (sin(DEST_Lat) - (sin(QTH_Lat) * cos(dist))) /
  169.                 (sin(dist) * cos(QTH_Lat));
  170.  
  171.         y = (sin(QTH_Lat) - (sin(DEST_Lat) * cos(dist))) /
  172.                 (sin(dist) * cos(DEST_Lat));
  173.  
  174.         x = acos(x) * RADIAN; /* change to degrees */
  175.     y = acos(y) * RADIAN;
  176.  
  177.         if (DEST_Long > QTH_Long)  {
  178.                 TO_Bearing = 360.0 - x;
  179.         FROM_Bearing = y;
  180.     } else  {
  181.         TO_Bearing = x;
  182.         FROM_Bearing = 360.0 - y;
  183.     }
  184.  
  185.         /* Computations complete, show answer */
  186.  
  187.         printf("\n  TO Bearing is %03.0f Degrees for %.0f Nautical Miles\n",
  188.                 TO_Bearing, range);
  189.         printf("FROM Bearing is %03.0f Degrees\n", FROM_Bearing);
  190.  
  191.         exit(0);
  192. }
  193.  
  194. /* EOF */
  195.